package login

import (
	"errors"
	"fmt"
	"learn/smart/config"
	"learn/smart/fetcher"
	"net/http"
	"net/url"
	"regexp"
)

type Result struct {
	SessionId string
	CSRFToken string
}

type Login struct {
	Fetcher *fetcher.Fetcher
	User    *config.User
	result  Result
}

type Data struct {
	CSRFMiddleWareToken string
	Username            string
	Password            string
}

func InitLogin(fetcher *fetcher.Fetcher, user *config.User) Login {
	return Login{Fetcher: fetcher, User: user}
}

var sessionRe = regexp.MustCompile(`sessionid=([^;]+);`)
var csrfRe = regexp.MustCompile(`csrftoken=([^;]+);`)

//var repairRe = regexp.MustCompile(`服务器维护中`)
func (login *Login) tryFirst() (Result, error) {
	resp, err := login.Fetcher.Get("/login/", nil)

	if err != nil {
		return Result{}, err
	}
	defer resp.Body.Close()

	result := Result{}

	setSessionIdAndCsrfToken(&result, resp)

	if result.CSRFToken == "" || result.SessionId == "" {
		return result, errors.New(fmt.Sprintf("CSRFToken || SessionId获取失败 StatusCode: %d", resp.StatusCode))
	}

	return result, nil
}

func setSessionIdAndCsrfToken(result *Result, resp *http.Response) {
	for _, v := range resp.Header["Set-Cookie"] {
		sm := sessionRe.FindSubmatch([]byte(v))
		if len(sm) >= 2 {
			result.SessionId = string(sm[1])
		}

		cm := csrfRe.FindSubmatch([]byte(v))
		if len(cm) >= 2 {
			result.CSRFToken = string(cm[1])
		}
	}
}

func (login *Login) Do() {
	login.Fetcher.SetHeader("Host", "www.igxe.cn")
	login.Fetcher.SetHeader("Referer", "https://www.igxe.cn/login/")

	result, err := login.tryFirst()

	if err != nil {
		fmt.Println(err)
		for i := 0; i < 3; i++ {
			fmt.Println("重试再次登录")
			result, err = login.tryFirst()
			if err == nil {
				break
			}
		}
	}

	if err != nil {
		fmt.Println(err)
		return
	}

	rm := make(map[string]string)
	rm["Cookie"] = "csrftoken=" + result.CSRFToken

	data := url.Values{}

	data.Add("csrfmiddlewaretoken", result.CSRFToken)
	data.Add("username", login.User.Username)
	data.Add("password", login.User.Password)
	data.Add("remember", "on")
	data.Add("check-user-pro", "true")

	resp, err := login.Fetcher.Post("/user_login", data, rm)

	if err != nil {
		for i := 0; i < 3; i++ {
			fmt.Println("重试请求user_login")
			resp, err = login.Fetcher.Post("/user_login", data, rm)
			if err == nil {
				break
			}
		}
	}

	if err != nil {
		fmt.Println(err)
		return
	}
	defer resp.Body.Close()

	setSessionIdAndCsrfToken(&result, resp)
	login.Fetcher.SetHeader("Cookie", fmt.Sprintf("csrftoken=%s; sessionid=%s;", result.CSRFToken, result.SessionId))
	login.User.CSRFToken = result.CSRFToken
	login.User.SessionId = result.SessionId
}
